//
//  WmcAMapSearchManager.swift
//  YPWatermarkCamera
//
//  Created by 周诗松 on 2022/4/8.
//

import AMapSearchKit
import Foundation

// MARK: - [WmcAMapSearchManager]

class WmcAMapSearchManager: NSObject {
    // Lifecycle

    override init() {
        super.init()
    }

    // Internal

    static var shared: WmcAMapSearchManager = {
        let manager = WmcAMapSearchManager()
        return manager
    }()

    static func requestPrivecy() {
        AMapSearchAPI.updatePrivacyShow(.didShow, privacyInfo: .didContain)
        AMapSearchAPI.updatePrivacyAgree(.didAgree)
    }

    /// 搜索天气
    /// - Parameters:
    ///   - city: 城市
    ///   - completion: 完成
    static func requestWeather(city: String, completion: @escaping (WmcWeatherModel) -> Void) {
        shared.searchWeatherCompletion = completion

        let request = AMapWeatherSearchRequest()
        request.city = city
        request.type = .live
        shared.searchAPI?.aMapWeatherSearch(request)
    }

    /// 行政区划查询请求
    /// - Parameters:
    ///   - keyword: 关键字
    ///   - pageSize: 分页数量
    ///   - pageIndex: 页码
    static func requestNearbyDistrict(keyword: String? = nil, pageSize: Int? = nil, pageIndex: Int? = nil) {
        let request = AMapDistrictSearchRequest()
        request.requireExtension = true

        if let keyword = keyword {
            request.keywords = keyword
        }
        if let pageSize = pageSize {
            request.offset = pageSize
        }
        if let pageIndex = pageIndex {
            request.page = pageIndex
        }

        shared.searchAPI?.aMapDistrictSearch(request)
    }

    /// 逆地理编码
    /// - Parameters:
    ///   - latitude: 纬度
    ///   - longitude: 经度
    ///   - completion: 完成
    static func requestReGeocode(latitude: CGFloat, longitude: CGFloat, success: @escaping (AMapReGeocode) -> Void, failure: @escaping ((error: Error, request: AMapReGeocodeSearchRequest)) -> Void) {
        shared.searchReGeocodeCompletion = success
        shared.searchReGeocodeFailure = failure

        let regeo = AMapReGeocodeSearchRequest()
        regeo.location = AMapGeoPoint.location(withLatitude: latitude, longitude: longitude)
        regeo.requireExtension = true

        shared.searchAPI?.aMapReGoecodeSearch(regeo)
    }

    /// 搜索poi
    /// - Parameters:
    ///   - location: 位置
    ///   - keyword: 关键字
    ///   - radius: 搜索半径
    ///   - pageSize: 分页数量
    ///   - pageIndex: 页码
    ///   - completion: 搜索成功
    ///   - failure: 搜索失败
    static func requestNearbyPOI(location: CLLocation, keyword: String? = nil, radius: Int? = nil, pageSize: Int? = nil, pageIndex: Int? = nil, completion: @escaping ((request: AMapPOIAroundSearchRequest?, response: AMapPOISearchResponse?)) -> Void, failure: (((error: Error, request: AMapPOIAroundSearchRequest)) -> Void)? = nil) {
        if shared.searchPOIRequest != nil {
            shared.searchAPI?.cancelAllRequests()
        }

        shared.searchPOICompletion = completion
        shared.searchPOIFailure = failure

        let request = AMapPOIAroundSearchRequest()
        request.location = AMapGeoPoint.location(withLatitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
        request.requireExtension = true

        if let keyword = keyword {
            request.keywords = keyword
        }
        if let radius = radius {
            request.radius = radius
        }
        if let pageSize = pageSize {
            request.offset = pageSize
        }
        if let pageIndex = pageIndex {
            request.page = pageIndex
        }

        shared.searchPOIRequest = request
        shared.searchAPI?.aMapPOIAroundSearch(request)
    }

    // Private

    /// 搜索poi
    private lazy var searchAPI: AMapSearchAPI? = {
        let api = AMapSearchAPI()
        api?.delegate = self
        api?.timeout = 10
        return api
    }()

    /// 搜索poi成功
    private var searchPOICompletion: (((request: AMapPOIAroundSearchRequest?, response: AMapPOISearchResponse?)) -> Void)?

    /// 搜索poi失败
    private var searchPOIFailure: (((error: Error, request: AMapPOIAroundSearchRequest)) -> Void)?
    
    /// 逆地理编码失败
    private var searchReGeocodeFailure: (((error: Error, request: AMapReGeocodeSearchRequest)) -> Void)?

    /// 搜索天气
    private var searchWeatherCompletion: ((WmcWeatherModel) -> Void)?

    /// 逆地理编码
    private var searchReGeocodeCompletion: ((AMapReGeocode) -> Void)?

    /// 搜索poi的request
    private var searchPOIRequest: AMapPOIAroundSearchRequest?
}

// MARK: - AMapSearchDelegate

extension WmcAMapSearchManager: AMapSearchDelegate {
    func onWeatherSearchDone(_ request: AMapWeatherSearchRequest!, response: AMapWeatherSearchResponse!) {
        let model = WmcWeatherModel()
        model.lives = response.lives
        model.forecasts = response.forecasts
        searchWeatherCompletion?(model)
    }

    func onPOISearchDone(_ request: AMapPOISearchBaseRequest!, response: AMapPOISearchResponse!) {
        searchPOICompletion?((searchPOIRequest, response))
        searchPOIRequest = nil
    }

    func onReGeocodeSearchDone(_ request: AMapReGeocodeSearchRequest!, response: AMapReGeocodeSearchResponse!) {
        searchReGeocodeCompletion?(response.regeocode)
    }

    func aMapSearchRequest(_ request: Any!, didFailWithError error: Error!) {
        if let aroundSearchRequest = request as? AMapPOIAroundSearchRequest {
            searchPOIFailure?((error, aroundSearchRequest))
        } else if let reGeocodeSearchRequest = request as? AMapReGeocodeSearchRequest {
            searchReGeocodeFailure?((error, reGeocodeSearchRequest))
        }
        searchPOIRequest = nil
    }

    func onDistrictSearchDone(_ request: AMapDistrictSearchRequest!, response: AMapDistrictSearchResponse!) {}
}

// MARK: - [WmcAutoUpdatePoiManager]

class WmcAutoUpdatePoiManager: NSObject {
    // Lifecycle

    override init() {
        super.init()
    }

    // Internal

    static var share: WmcAutoUpdatePoiManager = {
        let manager = WmcAutoUpdatePoiManager()
        return manager
    }()

    /// 搜索poi
    /// - Parameters:
    ///   - location: 位置
    ///   - keyword: 关键字
    ///   - radius: 搜索半径
    ///   - pageSize: 分页数量
    ///   - pageIndex: 页码
    ///   - completion: 搜索成功
    ///   - failure: 搜索失败
    static func requestNearbyPOI(location: CLLocation, keyword: String? = nil, radius: Int? = nil, pageSize: Int? = nil, pageIndex: Int? = nil, completion: @escaping ((request: AMapPOISearchBaseRequest, response: AMapPOISearchResponse?)) -> Void, failure: (((error: Error, request: AMapPOIAroundSearchRequest)) -> Void)? = nil) {
        if share.searchPOIRequest != nil {
            share.searchAPI?.cancelAllRequests()
        }

        share.searchPOICompletion = completion
        share.searchPOIFailure = failure

        let request = AMapPOIAroundSearchRequest()
        request.location = AMapGeoPoint.location(withLatitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
        request.requireExtension = true

        if let keyword = keyword {
            request.keywords = keyword
        }
        if let radius = radius {
            request.radius = radius
        }
        if let pageSize = pageSize {
            request.offset = pageSize
        }
        if let pageIndex = pageIndex {
            request.page = pageIndex
        }

        share.searchPOIRequest = request
        share.searchAPI?.aMapPOIAroundSearch(request)
        
        WmcLogManager.DebugLog(type: .location, log: "开始搜索poi")
    }

    // Private

    /// 搜索poi
    private lazy var searchAPI: AMapSearchAPI? = {
        let api = AMapSearchAPI()
        api?.delegate = self
        api?.timeout = 10
        return api
    }()

    /// 搜索poi成功
    private var searchPOICompletion: (((request: AMapPOISearchBaseRequest, response: AMapPOISearchResponse?)) -> Void)?

    /// 搜索poi失败
    private var searchPOIFailure: (((error: Error, request: AMapPOIAroundSearchRequest)) -> Void)?

    /// 搜索poi的request
    private var searchPOIRequest: AMapPOIAroundSearchRequest?
}

// MARK: - AMapSearchDelegate

extension WmcAutoUpdatePoiManager: AMapSearchDelegate {
    func onPOISearchDone(_ request: AMapPOISearchBaseRequest!, response: AMapPOISearchResponse!) {
        searchPOICompletion?((request, response))
        searchPOIRequest = nil
        WmcLogManager.DebugLog(type: .location, log: "搜索poi成功")
    }

    func aMapSearchRequest(_ request: Any!, didFailWithError error: Error!) {
        if let aroundSearchRequest = request as? AMapPOIAroundSearchRequest {
            searchPOIFailure?((error, aroundSearchRequest))
            searchPOIRequest = nil
            WmcLogManager.DebugLog(type: .location, log: "搜索poi失败")
        }
    }
}
